package com.qdlc.p2p.dal.mybatis.utils;

import java.io.IOException;
import java.io.InputStream;
import java.util.HashSet;
import java.util.Properties;
import java.util.Set;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathFactory;

import org.w3c.dom.Document;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

/**
 * 自定义MybatisGernerator
 *
 * @author linya
 */
public class ConfigurationableMybatisGenerator {

    private static final XPathFactory factory = XPathFactory.newInstance();

    //配置文件
    public static final String CONFIG_FILE = "/generatorConfig.xml";

    //属性文件
    private static final String PROPS_FILE = "/generatorConfig.properties";

    //XPath获取<table>节点路径
    private static final String TABLE_NODE = "generatorConfiguration/context/table";

    //<table>节点的别名，值设置成false|true，表示是否自动生成相应的代码
    private static final String TABLE_ATTRUBITE_GENERATE = "alias";

    //<table>节点的表名
    private static final String TABLE_ATTRUBITE_TABLENAME = "tableName";

    //属性文件中配置的schema
    private static final String PROPS_SCHEMA = "mybatis.schema";

    //配置mybatis.outputDirectory到属性文件中去
    private static final String PROPS_OUTPUTDIRECTORY = "mybatis.outputDirectory";

    private Properties properties;

    private Set<String> fullyQualifiedTableNames = new HashSet<String>();

    private String schema;

    private InputStream inputStream;

    public ConfigurationableMybatisGenerator() {
        loadGenerator();
    }

    private void loadGenerator() {
        initProperties();
    }

    private void initProperties() {
        try {
            properties = new Properties();
            properties.load(ConfigurationableMybatisGenerator.class.getResourceAsStream(PROPS_FILE));
            //设置文件
            setPropsOutputDirectory();
            //获取schema
            schema = String.valueOf(properties.get(PROPS_SCHEMA));
            //解析需要自动生成的Table名称
            parseFullQualifiedTableNames();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }


    /**
     * 设置文件输出的路径${mybatis.outputDirectory}的值
     *
     * @return
     */
    private void setPropsOutputDirectory() {
        String classPath = ConfigurationableMybatisGenerator.class.getResource("/").getPath();
        String sourcePath = classPath.replace("target/classes", "src/main/java").replace("target/test-classes", "src/main/java");
        properties.put(PROPS_OUTPUTDIRECTORY, sourcePath);
    }


    /**
     * 功能： 获取fullyQualifiedTableNames的集合数据，该集合数据存放的是需要自动生成代码的表的信息，格式为
     * schame.tablename
     * 1. schame从属性文件中获取，tablename从<table>节点属性中获取
     * 2. 为了每次执行是不都全部重新生成所有表，使用<table generate="true">来表示需要自动生成代码，
     * 解析出<table>节点，如果节点属性generate=true表示要自动生成代码，否则不生成代码
     * 3. fullyQualifiedTableNames为null或空时，表示自动生成所有<table>节点配置的表
     *
     * @return Set
     */
    public void parseFullQualifiedTableNames() {
        try {
            //获取<table>节点
            XPath xpath = factory.newXPath();
            DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
            inputStream = ConfigurationableMybatisGenerator.class.getResourceAsStream(CONFIG_FILE);
            Document root = builder.parse(inputStream);
            NodeList tableList = (NodeList) xpath.evaluate(TABLE_NODE, root, XPathConstants.NODESET);

            //遍历<table>节点
            for (int i = 0; i < tableList.getLength(); i++) {
                Node table = tableList.item(i);
                qualifiedTableName(table);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

    /**
     * 处理<table>节点是否需要自动生成代码
     * <table generate="true">表示需要生成
     *
     * @param table
     */
    private void qualifiedTableName(Node table) {
        //获取节点属性并遍历
        NamedNodeMap nnm = table.getAttributes();
        boolean generate = false;
        String tablename = null;
        boolean hasGenerateAttr = false;
        for (int j = 0; j < nnm.getLength(); j++) {
            Node attribute = nnm.item(j);
            String value = attribute.getNodeValue();
            String name = attribute.getNodeName();
            //获取generate属性
            if (TABLE_ATTRUBITE_GENERATE.equals(name)) {
                try {
                    hasGenerateAttr = true;
                    generate = Boolean.valueOf(value);
                } catch (Exception e) {
                    generate = false;
                }
                //获取tableName属性
            } else if (TABLE_ATTRUBITE_TABLENAME.equals(name)) {
                tablename = value;
            }
        }

        //按照schame.tablename格式存入到fullyQualifiedTableNames
        if ((!hasGenerateAttr || generate) && tablename != null) {
            fullyQualifiedTableNames.add(schema + "." + tablename);
        }
    }

    public Properties getProperties() {
        return properties;
    }

    public Set<String> getFullyQualifiedTableNames() {
        return fullyQualifiedTableNames;
    }

    public InputStream getInputStream() {
        return inputStream;
    }

    public void close() {
        try {
            if (inputStream != null) {
                inputStream.close();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
